package cn.com.yang.serializable;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.JavaSerializer;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Base64;

/**
 * kryo序列化操作
 *
 * @Author 杨亿金
 * @Date 2021/12/28 21:52
 * @CopyRight
 * @Version
 */

/**
 * Kyro序列化是主流的比较成熟的序列化方案之一，目前广泛使用在大数据组件中，
 * 比如Hive、Storm等，性能比起Hessian还要优越，但是缺陷较明显，不支持跨语言交互，
 * 在dubbo2.6.x版本开始已经加入了Kyro序列化的支持
 *。
 */
public class TestKryo {

    /**
     * kryo序列化对象
     *
     * @param obj 待序列化的对象
     * @param <T>
     * @return 序列化后的字符串
     */
    @Test
    public <T extends Serializable> String serializableObject(T obj) {
        Kryo kryo = new Kryo();
        kryo.setReferences(false);
        kryo.register(obj.getClass(), new JavaSerializer());
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Output output = new Output(byteArrayOutputStream);
        kryo.writeClassAndObject(output, obj);
        output.flush();
        output.close();
        byte[] bytes = byteArrayOutputStream.toByteArray();
        try {
            byteArrayOutputStream.flush();
            byteArrayOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 反序列化
     *
     * @param obgjstr
     * @param tClass
     * @param <T>
     * @return
     */
    @Test
    public <T extends Serializable> T deserializableObject(String obgjstr, Class<T> tClass) {
        Kryo kryo = new Kryo();
        kryo.setReferences(false);
        kryo.register(tClass, new JavaSerializer());
        ByteArrayInputStream byteArrayOutputStream = new ByteArrayInputStream(Base64.getDecoder().decode(obgjstr));
        Input input = new Input(byteArrayOutputStream);
        return (T) kryo.readClassAndObject(input);
    }
}
